package com.cyzy.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyzy.dto.CropDto;
import com.cyzy.dto.MyAllAdoptOrderDto;
import com.cyzy.dto.PlotOrdersPayDto;
import com.cyzy.dto.Result;
import com.cyzy.mapper.PlotOrdersMapper;
import com.cyzy.mapper.UserMapper;
import com.cyzy.pojo.*;
import com.cyzy.service.PlotOrdersService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class PlotOrdersServiceImpl extends ServiceImpl<PlotOrdersMapper, PlotOrders> implements PlotOrdersService {
    @Autowired
    private PlotOrdersMapper plotOrdersMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    // 缓存过期时间
    private static final long CACHE_EXPIRE_TIME = 3600;
//    @Qualifier("conversionService")
//    @Autowired
//    private ConversionService conversionService;

    @Override
    public int addOrder(PlotOrders plotOrders) {
        int i= plotOrdersMapper.insert(plotOrders);
        return i;
    }

    @Override
    public int updateOrder(PlotOrders plotOrders) {
        LambdaUpdateWrapper<PlotOrders> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PlotOrders::getPlotOrderNum,plotOrders.getPlotOrderNum());
        int update = plotOrdersMapper.update(plotOrders,wrapper);
        return update;
    }

    @Override
    public String payOrder(PlotOrdersPayDto plotOrders) {
        User user = new User();
        PlotOrders selectedPlotOrders = this.selectByOrderNum(plotOrders.getPlotOrderNum());
        //判断支付密码是否正确
        String cacheKey = "user:" + plotOrders.getUserId() + ":balance";
        // 1. 先从缓存获取
        String cachedData = stringRedisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
             user = JSON.parseObject(cachedData, User.class);

        }else {
            // 2. 缓存未命中，查询数据库
            user = userMapper.selectById(plotOrders.getUserId());
            if (user == null){
                return ("用户不存在");
            };
        }

      //输入的支付密码和用户的支付密码一致
        if (user.getUserPayPwd()==null){
            return "您未设置支付密码";
        }
        if (DigestUtils.md5DigestAsHex(plotOrders.getUserPayPwd().getBytes()).equals(user.getUserPayPwd())){
            LambdaUpdateWrapper<PlotOrders> lambdaUpdate = new LambdaUpdateWrapper<>();
            LambdaUpdateWrapper<User> lambdaUpdate1 = new LambdaUpdateWrapper<>();
            //修改支付状态
            lambdaUpdate.eq(PlotOrders::getPlotOrderNum, selectedPlotOrders.getPlotOrderNum())
                    .set(PlotOrders::getPlotOrderStatus, 1);
            //修改用户余额
            if (user.getUserMoney()>=plotOrders.getOrderAmount()){
                lambdaUpdate1.eq(User::getUserId, plotOrders.getUserId())
                        .set(User::getUserMoney,user.getUserMoney()-plotOrders.getOrderAmount());
            }
            else {
                return "余额不足";
            }


            int i = plotOrdersMapper.update(null,lambdaUpdate);
//            userMapper.update(null,lambdaUpdate1);
            // 2. 删除缓存
            stringRedisTemplate.delete(cacheKey);
            //订单状态未修改
            if (i == 0) {
                return "订单失效或已支付";
            }
            userMapper.update(null,lambdaUpdate1);
            return "支付成功";
        }else {
            return "支付密码错误";
        }



    }

    @Override
    public PlotOrders selectByOrderNum(String plotOrderNum) {
//        LambdaUpdateWrapper<PlotOrders> lambdaUpdate = new LambdaUpdateWrapper<>();
//        lambdaUpdate.eq(PlotOrders::getPlotOrderNum,plotOrderNum);
//        PlotOrders plotOrders = plotOrdersMapper.selectOne(lambdaUpdate);
        MPJLambdaWrapper<PlotOrders> lambdaUpdate = new MPJLambdaWrapper<>();
        lambdaUpdate
                .selectAs(Field::getFieldImage, PlotOrders::getFieldImage)
                .selectAs(Field::getFieldName, PlotOrders::getFieldName)
                .selectAs(PlotOrders::getPlotId, PlotOrders::getPlotOrderId)
                .selectAs(PlotOrders::getPlotOrderStatus, PlotOrders::getPlotOrderStatus)
                .selectAs(PlotOrders::getPlotOrderNum, PlotOrders::getPlotOrderNum)
                .selectAs(PlotOrders::getUserId, PlotOrders::getUserId)
                .selectAs(PlotOrders::getPlotId, PlotOrders::getPlotId)
                .selectAs(PlotOrders::getLeastTime, PlotOrders::getLeastTime)
                .selectAs(PlotOrders::getOrderAmount, PlotOrders::getOrderAmount)
                .selectAs(PlotOrders::getServiceId, PlotOrders::getServiceId)
                .selectAs(PlotOrders::getLeastStartTime, PlotOrders::getLeastStartTime)
                .selectAs(PlotOrders::getLeastEndTime, PlotOrders::getLeastEndTime)
                .selectAs(PlotOrders::getLeastEndTime, PlotOrders::getLeastEndTime)
                .selectAs(PlotOrders::getCreatedAt, PlotOrders::getCreatedAt)
                .selectAs(PlotOrders::getUpdatedAt, PlotOrders::getUpdatedAt)
                .selectAs(Plot::getPlotName, PlotOrders::getPlotName)
                .selectAs(Plot::getPlotArea, PlotOrders::getPlotArea)
                .leftJoin(Plot.class, Plot::getPlotId, PlotOrders::getPlotId)

                .leftJoin(Field.class, Field::getFieldId, Plot::getFieldId)
                .eq(PlotOrders::getPlotOrderNum,plotOrderNum);

//                .in(PlotOrders::getPlotOrderStatus,0,1,2);
        PlotOrders plotOrders = plotOrdersMapper.selectOne(lambdaUpdate);
        return plotOrders;
    }

    @Override
    public List<CropDto> selectCropByOrderNum(String plotOrderNum) {
        List<CropDto> cropDtos = plotOrdersMapper.selectCropsByOrderNum(plotOrderNum);
        return cropDtos;
    }

    @Override
    public PlotOrders selectUnpayOrder(Long userId) {
        LambdaUpdateWrapper<PlotOrders> lambdaUpdate = new LambdaUpdateWrapper<>();
        lambdaUpdate.eq(PlotOrders::getUserId,userId).eq(PlotOrders::getPlotOrderStatus,0);
        PlotOrders plotOrders = plotOrdersMapper.selectOne(lambdaUpdate);
        return plotOrders;
    }

    @Override
    public List<PlotOrders> selectOrdersByUserId(Long userId,Long plotOrderStatus) {
        MPJLambdaWrapper<PlotOrders> lambdaUpdate = new MPJLambdaWrapper<>();
        lambdaUpdate
                .selectAs(Field::getFieldImage, PlotOrders::getFieldImage)
                .selectAs(Field::getFieldName, PlotOrders::getFieldName)
                .selectAs(PlotOrders::getPlotId, PlotOrders::getPlotOrderId)
                .selectAs(PlotOrders::getPlotOrderStatus, PlotOrders::getPlotOrderStatus)
                .selectAs(PlotOrders::getPlotOrderNum, PlotOrders::getPlotOrderNum)
                .selectAs(PlotOrders::getUserId, PlotOrders::getUserId)
                .selectAs(PlotOrders::getPlotId, PlotOrders::getPlotId)
                .selectAs(PlotOrders::getLeastTime, PlotOrders::getLeastTime)
                .selectAs(PlotOrders::getOrderAmount, PlotOrders::getOrderAmount)
                .selectAs(PlotOrders::getServiceId, PlotOrders::getServiceId)
                .selectAs(PlotOrders::getLeastStartTime, PlotOrders::getLeastStartTime)
                .selectAs(PlotOrders::getLeastEndTime, PlotOrders::getLeastEndTime)
                .selectAs(PlotOrders::getLeastEndTime, PlotOrders::getLeastEndTime)
                .selectAs(PlotOrders::getCreatedAt, PlotOrders::getCreatedAt)
                .selectAs(PlotOrders::getUpdatedAt, PlotOrders::getUpdatedAt)
                .selectAs(Plot::getPlotName, PlotOrders::getPlotName)
                .selectAs(Plot::getPlotArea, PlotOrders::getPlotArea)
                .leftJoin(Plot.class, Plot::getPlotId, PlotOrders::getPlotId)

                .leftJoin(Field.class, Field::getFieldId, Plot::getFieldId)
                .eq(PlotOrders::getUserId,userId)

                .in(PlotOrders::getPlotOrderStatus,0,1,2);
        List<PlotOrders> plotOrders = plotOrdersMapper.selectList(lambdaUpdate);
        return plotOrders;
    }

    @Override
    public List<PlotOrders> getOrdersFromCache(String cacheKey) {
        // 从Redis获取缓存数据
        List<PlotOrders> cachedList = (List<PlotOrders>)JSON.parse(redisTemplate.opsForValue().get(cacheKey)) ;
        return cachedList;
    }
    @Override
    public void cacheOrders(String cacheKey, List<PlotOrders> orders) {
        // 将订单列表存入Redis缓存
        redisTemplate.opsForValue().set(cacheKey,JSON.toJSONString(orders) , CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
    }
}
